package de.cbf.cam.dsa.facet.sf.edit;

import java.beans.IndexedPropertyChangeEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.swt.widgets.Control;

import de.cbf.cam.dsa.facet.sf.FacetSf;
import de.cbf.cam.dsa.facet.sf.constants.ESfType;
import de.cbf.cam.dsa.facet.sf.helper.PrerequisiteSfReference;
import de.cbf.util.controller.ControllerEvent;
import de.cbf.util.controller.IListenerController;
import de.cbf.util.entity.facet.edit.composites.factorys.AbstractFacetSectionFactory;
import de.cbf.util.entity.facet.edit.controller.AbstractControllerEditFacet;
import de.cbf.util.entity.facet.persistence.resolver.IServiceResolverEntity;
import de.cbf.util.ui.controller.ControllerTableEdit;
import de.cbf.util.ui.listener.AbstractUIChangeListener;
import de.cbf.util.ui.listener.IUiChangeListener;
import de.cbf.util.ui.listener.UiChangeEvent;

public class ControllerEditorFacetSf extends AbstractControllerEditFacet<FacetSf> {
	private static final Log logger = LogFactory.getLog(ControllerEditorFacetSf.class);
	
	
	public static final String TEXT_STATE_EVENT_TalentType_WARNING		= FacetSf.TEXT_UNSET_SfType;	
	
	public static final StateEvent STATE_EVENT_SfType_WARNING		= new StateEvent(TEXT_STATE_EVENT_TalentType_WARNING, StateEvent.STATE_WARNING);	 	
			
	
	protected CompositeEditSf compositeEditSf;
	
	protected NumberFormat formatInteger;
		
	protected ControllerEditPrerequisiteSfs	controllerPrerequisiteSfsEdit;
	
	@Override
	protected void init() {
		super.init();
		formatInteger = NumberFormat.getIntegerInstance();		
		setControllerPrereqSfEdit(new ControllerEditPrerequisiteSfs());		
	}
	
	@Override
	protected AbstractFacetSectionFactory createSectionFactory() {		
		return new SectionFactorySf();
	}

	@Override
	protected FacetSf createNewFacet() {
		return new FacetSf();
	}

	@Override
	public Class<FacetSf> getFacetClass() {
		return FacetSf.class;
	}
	
	public void modifyTalentType(String newSfType) {	
		if(facet == null) return;	
		facet.setSfType(ESfType.getByName(newSfType));		
	}
		
	public void modifyPrequisiteSf(List<PrerequisiteSfReference> newPrerequisiteSfRefs) {
		if(facet == null) return;
//		facet.setCompensationTalents(newPrerequisiteSfRefs);
	}
	
	public void updateSfType(ESfType sfType) {
		if(compositeEditSf != null){
			if(sfType != null && ! sfType.equals(FacetSf.UNSET_SfType)){				
				compositeEditSf.setSfType(ESfType.getNameOf(sfType));
				removeStateEvent(STATE_EVENT_SfType_WARNING);
			}else{
				compositeEditSf.setSfType(null);
				if(facet != null){
					addStateEvent(STATE_EVENT_SfType_WARNING);
				}				
			}				
		}			
	}	
	
	public void updatePrerequisiteSf(List<PrerequisiteSfReference> newPrerequisiteSfs) {
		//because sub controller updates alone there should be no work to be done here
//		if(controllerPrerequisiteSfsEdit != null){
//			controllerPrerequisiteSfsEdit.setData(newCompensationTalents);
//		}				
	}	
	
	@Override
	protected void updateAll(FacetSf facet) {		
		logger.trace("Updating all data in FacetSf with: "+facet);
		updateSfType			(facet.getSfType());		
//		updatePrerequisiteSf	(facet.getCompensationTalents());		
	}
	
	@Override
	protected void updateClearUI() {		
		updateSfType			(null);		
		updatePrerequisiteSf	(new ArrayList<PrerequisiteSfReference>());
	}
	
	@Override
	protected void preSetSection() {
		super.preSetSection();
		if(section != null){
			Control client = section.getClient();
			if (client instanceof CompositeEditSf) {
				compositeEditSf = (CompositeEditSf) client;
				deRegisterUIListeners(compositeEditSf);				
			}else{
				logger.error("wrong client in section: expected "+CompositeEditSf.class.getSimpleName()+
						" got: "+client.getClass().getSimpleName());
			}			
			if(controllerPrerequisiteSfsEdit != null){
				controllerPrerequisiteSfsEdit.setComposite(null);
			}	
		}		
	}

	@Override
	protected void postSetSection() {
		super.postSetSection();
		Control client = section.getClient();
		if (client instanceof CompositeEditSf) {
			compositeEditSf = (CompositeEditSf) client;
			registerUIListeners(compositeEditSf);			
			if(controllerPrerequisiteSfsEdit != null){
				controllerPrerequisiteSfsEdit.setComposite(compositeEditSf.getCompositePrereqSf());
			}				
			provideComboInitData(compositeEditSf);
		}else{
			logger.error("wrong client in section: expected "+CompositeEditSf.class.getSimpleName()+
					" got: "+client.getClass().getSimpleName());
		}
	}

	protected void registerUIListeners(CompositeEditSf compositeEditTalent) {
		compositeEditTalent.registerUIListener(getUilFacetTalent());
	}

	protected void deRegisterUIListeners(CompositeEditSf compositeEditTalent) {
		compositeEditTalent.deRegisterUIListener(getUilFacetTalent());
	}
	
	/**
	 * method to provide data to combo fields in composite<br>
	 * here for sf type and attributes
	 * @param compositeEditSf
	 */
	protected void provideComboInitData(CompositeEditSf compositeEditTalent) {
		ESfType[] typeValues = ESfType.values();
		String[] sfTypes = new String[typeValues.length];
		for (int i = 0; i < typeValues.length; i++) {			
			sfTypes[i] = ESfType.getNameOf(typeValues[i]);
		}		 		
		compositeEditTalent.setPossibleSfTypes(sfTypes);			
	}

	@Override
	protected void preSetNewFacet() {
		super.preSetNewFacet();
		if(facet != null){
			deRegisterModelListeners(facet);			
		}		
		if(controllerPrerequisiteSfsEdit != null){
			controllerPrerequisiteSfsEdit.setData(null);
		}		
	}

	@Override
	protected void postSetNewFacet() {
		super.postSetNewFacet();
		if(facet != null){
			registerModelListeners(facet);			
			if(controllerPrerequisiteSfsEdit != null){
				controllerPrerequisiteSfsEdit.setData(facet.getPrerequisiteSfs());
			}	
		}		
	}

	protected void registerModelListeners(FacetSf facet) {
		facet.getPropertyChangeSupport().addPropertyChangeListener(getPclFacetTalent());
	}

	protected void deRegisterModelListeners(FacetSf facet) {
		facet.getPropertyChangeSupport().removePropertyChangeListener(getPclFacetTalent());
	}
	
	protected IUiChangeListener getUilFacetTalent() {
		if(uilFacetTalent == null){
			uilFacetTalent = new UILFacetTalent();
		}
		return uilFacetTalent;
	}
	
	/**
	 * @return the controllerSpecializationsEdit
	 */
	public ControllerTableEdit<PrerequisiteSfReference> getControllerPrerequisiteSfsEdit() {
		return controllerPrerequisiteSfsEdit;
	}

	/**
	 * @param newControllerPrerequisiteSfsEdit the controllerSpecializationsEdit to set
	 */
	public void setControllerPrereqSfEdit(ControllerEditPrerequisiteSfs newControllerPrerequisiteSfsEdit) {
		deRegisterSubControllerPrerequisiteSfsListeners(controllerPrerequisiteSfsEdit);
		controllerPrerequisiteSfsEdit = newControllerPrerequisiteSfsEdit;
		registerSubControllerPrerequisiteSfsListeners(controllerPrerequisiteSfsEdit);		
	}	
	
	protected void registerSubControllerPrerequisiteSfsListeners(
			ControllerTableEdit<PrerequisiteSfReference> subController) {
		if(subController != null){
			subController.registerEventListener(getCelPrerequisiteSfs());
		}
	}

	protected void deRegisterSubControllerPrerequisiteSfsListeners(
			ControllerTableEdit<PrerequisiteSfReference> subController) {
		if(subController != null){
			subController.deRegisterEventListener(getCelPrerequisiteSfs());
		}		
	}

	public void setSfResolver(IServiceResolverEntity serviceResolverTalents) {
		if(controllerPrerequisiteSfsEdit != null){
			controllerPrerequisiteSfsEdit.setSfResolver(serviceResolverTalents);
		}		
	}	

	protected UILFacetTalent uilFacetTalent;
	protected class UILFacetTalent extends AbstractUIChangeListener{
		@Override
		public void uiChanged(UiChangeEvent event) {
			int index = event.getIndex();
			switch (index) {
				case CompositeEditSf.EVT_EDIT_TALENT_TYPE:{
					Object obj = event.getNewValue();
					if (obj instanceof String) {
						String talentType = (String) obj;
						modifyTalentType(talentType);
					}
					break;
				}
				
				default:
					logger.warn("Unknown UI-Changed-Event-Index: "+index);
					break;
			}
		}
	}
	
	protected PCLFacetTalent pclFacetTalent;
	protected PropertyChangeListener getPclFacetTalent() {
		if(pclFacetTalent == null){
			pclFacetTalent = new PCLFacetTalent();
		}
		return pclFacetTalent;
	}	
	
	protected class PCLFacetTalent implements PropertyChangeListener{
		@Override
		public void propertyChange(PropertyChangeEvent evt) {
			if (evt instanceof IndexedPropertyChangeEvent) {
				IndexedPropertyChangeEvent idxEvent = (IndexedPropertyChangeEvent) evt;
				int index = idxEvent.getIndex();
				switch (index) {
					//ignore changes of uuidHeader values and name				
					case FacetSf.PI_UUID:
					case FacetSf.PI_DATASOURCE:
					case FacetSf.PI_DELETED:
					case FacetSf.PI_NAME:{
						break;
					}
					case FacetSf.PI_SfType:{
						if (idxEvent.getNewValue() instanceof ESfType) {
							ESfType sfType = (ESfType) idxEvent.getNewValue();
							updateSfType(sfType);
						}
						break;
					}		
					
					case FacetSf.PI_PrerequisiteSf:{
						if (idxEvent.getNewValue() instanceof List) {
							List<?> value = (List<?>) idxEvent.getNewValue();
							List<PrerequisiteSfReference> valueList = new ArrayList<PrerequisiteSfReference>();
							for (Object obj : value) {
								if (obj instanceof PrerequisiteSfReference) {
									PrerequisiteSfReference string = (PrerequisiteSfReference) obj;
									valueList.add(string);
								}
							}
							updatePrerequisiteSf(valueList);
						}
						break;
					}		
					default:
						logger.warn("Unknown PCL-Index: "+index);
						break;
				}
			}
		}
	}

	protected CELPrerequisiteSfs celPrerequisiteSfs;	
	protected IListenerController getCelPrerequisiteSfs() {
		if(celPrerequisiteSfs == null){
			celPrerequisiteSfs = new CELPrerequisiteSfs();
		}
		return celPrerequisiteSfs;
	}
	protected class CELPrerequisiteSfs implements IListenerController{
		@Override
		public int handleControllerEvent(ControllerEvent event) {
			if(ControllerTableEdit.CTRL_EVT_CODE_TABLE_UPDATED.equals(event.getEventCode())){
				List<PrerequisiteSfReference> PrerequisiteSfRefs = new ArrayList<PrerequisiteSfReference>();
				List<Object> parameters = event.getParameters();
				for (Object object : parameters) {
					if (object instanceof List) {
						List<?> list = (List<?>) object;
						for (Object listObject : list) {
							if (listObject instanceof PrerequisiteSfReference) {
								PrerequisiteSfReference string = (PrerequisiteSfReference) listObject;
								PrerequisiteSfRefs.add(string);								
							}
						}
					}
				}
				modifyPrequisiteSf(PrerequisiteSfRefs);
			}
			return 0;
		}		
	}
}
